package sos

import hce.core.common.archetyped.Locatable
import hce.core.composition.Composition
import tablasMaestras.Cie10Trauma
import demographic.identity.Lugar
import grails.converters.JSON
import java.text.SimpleDateFormat
import demographic.identity.PersonNamePatient
import demographic.party.Person
import com.vividsolutions.jts.geom.Coordinate
import com.vividsolutions.jts.geom.PrecisionModel
import com.vividsolutions.jts.geom.Point
import com.vividsolutions.jts.operation.distance.DistanceOp


class SalaSituacionalController {
    def hceService
    def today = new Date(new Date().getTime() + (24 * 60 * 60 * 1000))
    SimpleDateFormat sdf = new java.text.SimpleDateFormat("dd-MM-yyyy")

    def diagnosticosFinder = {
        def diagnosticosFound = Cie10Trauma.withCriteria{
            ilike 'nombre', params.term + '%'
        }
        render (diagnosticosFound.nombre as JSON)
    }

    def index = {
        def estados = Lugar.findAllByTipolugarLike("Estado")
        return [estados: estados]
    }

    def filtrar = {
        def estado = params.entidresid
        if (params.entidresid != '-1'){estado = params.entidresid.toLong()}
        def municipio = params.municresid
        if (params.municresid != '-1'){municipio = params.municresid.toLong()}
        def parroquia = params.direccion
        if (params.direccion != '-1'){parroquia = params.direccion.toLong()}
        def fecha_inicio = params.fecha_inicio
        def fecha_fin = params.fecha_fin
        if (params.fecha_inicio == null){fecha_inicio = sdf.parse("10-02-2000")}
        if (params.fecha_fin == null){ fecha_fin = today}
        def edadMin = null
        def edadMax = null
        def sexo = params.sexo
        def diagnostico = null
        if (params.diagnostico!=""){
            diagnostico = Cie10Trauma.findByNombre(params.diagnostico).codigo
            if (diagnostico==null) {
                diagnostico = Cie10Trauma.findByNombre(params.diagnostico)
            }
        }
        switch(params.edad){
            case 'Entre 0 y 14 años':
            edadMin = 0
            edadMax = 14
            break
            case 'Entre 15 y 29 años':
                edadMin = 15
                edadMax = 29
            break
            case 'Entre 30 y 44 años':
                edadMin = 30
                edadMax = 44
            break
            case 'Entre 45 y 59 años':
                edadMin = 45
                edadMax = 59
                break
            case 'Mas de 60 años':
                edadMin = 60
                edadMax = 100
            break
        }
        def list = [estado, municipio, parroquia, fecha_inicio,fecha_fin,edadMin,edadMax,sexo,diagnostico]
        def patients = getPuntos(list)
        def estadistica = patients.last();
        patients.remove(patients.size()-1)
        render """
                   <div id='patientList' value='${patients}'></div>
                   <div id='estadisticas' value='${estadistica as JSON}'></div>
               """
    }

    def List getPuntos(Collection parametros){
        List<Composition> compositions = null
        def List patients = []
        def cantidadCasos = 0
        def Estados = []
        def Municipios = []
        def Parroquias = []
        def sumaEdad = 0
        def Femenino = 0
        def Masculino = 0
        def Diagnosticos = []
        def patientId = 0
        def patientData = []
        def lastPatient = 0
        compositions = hceService.getAllCompositionForDate(parametros[3]-1, parametros[4]+1)
        if (compositions != null) {
            compositions.each {
                def composition = Composition.get(it.id)
                def patient = hceService.getPatientFromComposition(composition)
                if (patient){
                    def datos = patient.identities.find {it.purpose == 'PersonNamePatient'}
                    def edad = getAge(patient.getFechaNacimiento())
                    if (datos != null){
                        if (filtro(parametros,datos,patient)){
                            def elemento = hceService.getCompositionContentItemForTemplate(composition, "DIAGNOSTICO-diagnosticos")
                            if (elemento != null) {
                                def rmNode = Locatable.findByName(elemento.name) //enlace al nodo de la composition en el modelo de referenci
                                def rmNodeData = rmNode.data
                                def rmNodeDataEvents = rmNodeData.events
                                def element = rmNodeDataEvents[0].data.items
                                element.each {
                                    if (it.name.value != "Descripción") { // identifico si el nodo el arquetipo de diagnostico hace referencia al diagnostico codificado o a la impresion diagnostica (Ver Arquetipo EHR-OBSERVATION.diagnosticos)
                                        def diagnostico = Cie10Trauma.findByCodigo(it.value.definingCode.codeString)
                                        if (diagnostico==null){
                                            diagnostico = Cie10Trauma.findBySubgrupo(it.value.definingCode.codeString)
                                        }
                                        if (diagnostico != null) {
                                            if (parametros[8]==null || parametros[8]==diagnostico || parametros[8]==diagnostico.codigo) {
                                                    def coordenadas = null
                                                    def id = null
                                                    if (datos.avenidacalle.isNumber()){
                                                        coordenadas = Lugar.findById(datos.avenidacalle.toLong()).coordenadas
                                                        id = datos.avenidacalle.toLong()
                                                    }else{
                                                        if (datos.direccion.coordenadas != null){
                                                            coordenadas = datos.direccion.coordenadas
                                                            id = datos.direccion.id
                                                        }else{
                                                            if (datos.direccion.padre.coordenadas != null){
                                                                coordenadas = datos.direccion.padre.coordenadas
                                                                id = datos.direccion.padre.id
                                                            }else{
                                                                coordenadas = datos.direccion.padre.padre.coordenadas
                                                                id = datos.direccion.padre.padre.id
                                                            }
                                                        }
                                                    }
                                                    if (patientId == patient.id){
                                                        def aux =  patients.get(lastPatient-1).get(7) + "-" + diagnostico.nombre
                                                        patients.get(lastPatient-1).remove(7)
                                                        patients.get(lastPatient-1).add(aux)
                                                    }else{
                                                        patientData = [
                                                        id,
                                                        datos.direccion.padre.padre.nombre,
                                                        datos.direccion.padre.nombre,
                                                        datos.direccion.nombre,
                                                        coordenadas,
                                                        edad,
                                                        patient.sexo,
                                                        diagnostico.nombre]
                                                        patients.add(patientData)
                                                        cantidadCasos++;
                                                        Estados.add(datos.direccion.padre.padre.id);
                                                        Municipios.add(datos.direccion.padre.id);
                                                        Parroquias.add(datos.direccion.id);
                                                        sumaEdad = sumaEdad + edad
                                                        if (patient.sexo=='Masculino'){
                                                            Masculino++
                                                        }else{
                                                            Femenino++
                                                        }
                                                        lastPatient++
                                                    }
                                                    Diagnosticos.add(diagnostico.nombre);
                                                    patientId = patient.id;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        def total = [cantidadCasos,Estados,Municipios,Parroquias,sumaEdad,Femenino,Masculino,Diagnosticos]
        patients.add(total)
        return patients
    }

    def Object getAge(Date fechaNacimiento){
        use(groovy.time.TimeCategory) {
            def duration = today - fechaNacimiento
            def edad = duration.days/365
            return edad.toLong()
        }
    }

    def Boolean filtro(Collection parametros, PersonNamePatient datos,Person patient){
        def edad = getAge(patient.getFechaNacimiento())
        if (datos.direccion.padre.padre.id==parametros[0] || parametros[0]=='-1'){
            if (datos.direccion.padre.id==parametros[1] || parametros[1]=='-1'){
                if (datos.direccion.id==parametros[2] || parametros[2]=='-1'){
                    if ((parametros[5]==null && parametros[6]==null) || (parametros[5]<=edad && parametros[6]>=edad)){
                        if ((parametros[7]=="null" || parametros[7]==patient.sexo)){
                            return true
                        }
                    }
                }
            }
        }
    return false
    }

    def setEstadisticas = {
    def list
        if (params.evalFlag == false){
            list = params.estadistica
        }else{
            list = Eval.me(params.estadistica)
        }
        if (list[0]!=0){
            def IdEstados = list[1].unique().sort();
            def IdMunicipios = list[2].unique().sort();
            def IdParroquias = list[3].unique().sort();
            def Estados = []
            def Municipios = []
            def Parroquias = []
            IdEstados.collect{
                Estados.add(Lugar.findById(it))
            }
            IdMunicipios.collect{
                Municipios.add(Lugar.findById(it))
            }
            IdParroquias.collect{
                Parroquias.add(Lugar.findById(it))
            }
            def EdadPromedio =  Math.round((list[4].toLong()/list[0].toLong()) * 10) / 10

            render """
               <div id="Indicadores">
                    <p style="background-color:#f7f7f7;">
                        <label for="cantidadCasos">Casos</label>
                        <input type="text" id="CifraCantidadCasos" name="cifraCantidadCaso" value="${list[0]}" disabled="true">
                        <label for="estadosAfectados">Estados</label>
                        <select name="estadisticaEstado" class="selectci" id="estadisticaEstado">
                        """+Estados.collect{ """<option value="${it.id}">${it.nombre}</option>"""}+
                        """"</select><label for="municipiosAfectados">Municipios</label>
                        <select name="estadisticaMunicipio" class="selectci" id="estadisticaMunicipio">" +
                        """+Municipios.collect{ """<option value="${it.id}">${it.nombre}</option>"""}+
                        """</select><label for="parroquiasAfectadas">Parroquias</label>
                        <select name="estadisticaMunicipio" class="selectci" id="estadisticaMunicipio">" +
                        """+Parroquias.collect{ """<option value="${it.id}\">${it.nombre}</option>"""}+"""</select>
                    </p>
                    <p style="background-color:#f7f7f7;">
                        <label for="masculino">Femenino</label>
                        <input type="text" id="cifraMasculino" name="cifraMasculino" optionkey="id" value="${list[5]}" disabled="true">
                        <label for="femenino">Masculino</label>
                        <input type="text" id="cifraFemenino" name="cifraFemenino" optionkey="id" value="${list[6]}" disabled="true">
                        <label for="edad">Edad Promedio</label>
                        <input type="text" id="cifraEdad" name="cifraEdad" optionkey="id" value="${EdadPromedio}" disabled="true">
                        <label for="diagnosticos">Diagnotiscos</label>
                        <select name="estadisticaDiagnostico" class="selectci" id="estadisticaDiagnostico">""+
                        """+list[7].collect{ """<option value="">${it}</option>"""}+"""</select>
                    </p>
               </div>
               """
        }else{
            render """
               <div id="Indicadores">
                    <p style="background-color:#f7f7f7;">
                        <label for="cantidadCasos">Casos</label>
                        <input type="text" id="CifraCantidadCasos" name="cifraCantidadCaso" value="" disabled="true">
                        <label for="estadosAfectados">Estados</label>
                        <input type="text" id="CifraCantidadCasos" name="cifraCantidadCaso" value="" disabled="true">
                        <label for="municipiosAfectados">Municipios</label>
                        <input type="text" id="CifraCantidadCasos" name="cifraCantidadCaso" value="" disabled="true">
                        <label for="parroquiasAfectadas">Parroquias</label>
                        <input type="text" id="CifraCantidadCasos" name="cifraCantidadCaso" value="" disabled="true">
                    </p>
                    <p style="background-color:#f7f7f7;">
                        <label for="masculino">Femenino</label>
                        <input type="text" id="cifraMasculino" name="cifraMasculino" optionkey="id" value="" disabled="true">
                        <label for="femenino">Masculino</label>
                        <input type="text" id="cifraFemenino" name="cifraFemenino" optionkey="id" value="" disabled="true">
                        <label for="edad">Edad Promedio</label>
                        <input type="text" id="cifraEdad" name="cifraEdad" optionkey="id" value="" disabled="true">
                        <label for="diagnosticos">Diagnotiscos</label>
                        <input type="text" id="CifraCantidadCasos" name="cifraCantidadCaso" value="" disabled="true">
                    </p>
               </div>
               """
        }
    }

    def getDistanciaPuntos = {
        def latlon = params.coordenadas;
        def coordenadas = latlon.tokenize(',');
        def latitud = coordenadas[0].tokenize('lat=');
        def longitud =coordenadas[1].tokenize('lon=');
        def latitud_punto = latitud[1].toDouble()
        def longitud_punto = longitud[1].toDouble()
        def coordinate = new Coordinate(longitud_punto,latitud_punto)
        def precisionModel = new PrecisionModel()
        def punto = new Point(coordinate, precisionModel, 4326)
        def List pacientes_cercanos = getPatientsbyCoordinates(punto);
        def list = pacientes_cercanos.last();
        pacientes_cercanos.remove(pacientes_cercanos.size()-1)
        params.estadistica = list
        params.evalFlag = false
        render """
            <div id='patientList' value='${pacientes_cercanos}'></div>
            <div id='estadisticas' value='${list as JSON}'></div>
         """
    }

    def List getPatientsbyCoordinates(Point coordinate){
        List<Composition> compositions = null
        def List patients = []
        def cantidadCasos = 0
        def Estados = []
        def Municipios = []
        def Parroquias = []
        def sumaEdad = 0
        def Femenino = 0
        def Masculino = 0
        def Diagnosticos = []
        def patientId = 0
        def patientData = []
        def lastPatient = 0
        compositions = hceService.getAllCompositionForDate(sdf.parse("10-02-2000"), today)
        if (compositions != null) {
            compositions.each {
            def composition = Composition.get(it.id)
            def patient = hceService.getPatientFromComposition(composition)
                if (patient){
                    def edad = getAge(patient.getFechaNacimiento())
                    def datos = patient.identities.find {it.purpose == 'PersonNamePatient'}
                    if (datos != null){
                        def elemento = hceService.getCompositionContentItemForTemplate(composition, "DIAGNOSTICO-diagnosticos")
                        if (elemento != null) {
                            def rmNode = Locatable.findByName(elemento.name) //enlace al nodo de la composition en el modelo de referenci
                            def rmNodeData = rmNode.data
                            def rmNodeDataEvents = rmNodeData.events
                            def element = rmNodeDataEvents[0].data.items
                            element.each {
                                if (it.name.value != "Descripción") { // identifico si el nodo el arquetipo de diagnostico hace referencia al diagnostico codificado o a la impresion diagnostica (Ver Arquetipo EHR-OBSERVATION.diagnosticos)
                                    def diagnostico = Cie10Trauma.findByCodigo(it.value.definingCode.codeString)
                                    if (diagnostico==null){
                                        diagnostico = Cie10Trauma.findBySubgrupo(it.value.definingCode.codeString)
                                    }
                                    if (diagnostico != null) {
                                        def coordenadas = null
                                        def id = null
                                        if (datos.avenidacalle.isNumber()){
                                            coordenadas = Lugar.findById(datos.avenidacalle.toLong()).coordenadas
                                            id = datos.avenidacalle.toLong()
                                        }else{
                                            if (datos.direccion.coordenadas != null){
                                                coordenadas = datos.direccion.coordenadas
                                                id = datos.direccion.id
                                            }else{
                                                if (datos.direccion.padre.coordenadas != null){
                                                    coordenadas = datos.direccion.padre.coordenadas
                                                    id = datos.direccion.padre.id
                                                }else{
                                                    coordenadas = datos.direccion.padre.padre.coordenadas
                                                    id = datos.direccion.padre.padre.id
                                                }
                                            }
                                        }
                                        if (patientId == patient.id && patients.size() != 0){
                                            def aux =  patients.get(lastPatient-1).get(7) + "-" + diagnostico.nombre
                                            patients.get(lastPatient-1).remove(7)
                                            patients.get(lastPatient-1).add(aux)
                                        }else{
                                            def JTS = new DistanceOp(coordinate, coordenadas)
                                            def double distance = JTS.distance(coordinate, coordenadas)*100
                                            if (distance < 40){
                                                patientData = [
                                                        id,
                                                        datos.direccion.padre.padre.nombre,
                                                        datos.direccion.padre.nombre,
                                                        datos.direccion.nombre,
                                                        coordenadas,
                                                        edad,
                                                        patient.sexo,
                                                        diagnostico.nombre]
                                                patients.add(patientData)
                                                cantidadCasos++;
                                                Estados.add(datos.direccion.padre.padre.id);
                                                Municipios.add(datos.direccion.padre.id);
                                                Parroquias.add(datos.direccion.id);
                                                sumaEdad = sumaEdad + edad
                                                if (patient.sexo=='Masculino'){
                                                    Masculino++
                                                }else{
                                                    Femenino++
                                                }
                                                lastPatient++
                                                Diagnosticos.add(diagnostico.nombre);
                                            }
                                        }
                                        patientId = patient.id;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        def total = [cantidadCasos,Estados,Municipios,Parroquias,sumaEdad,Femenino,Masculino,Diagnosticos]
        patients.add(total)
        return patients
    }
}
